package com.tangyuan.ai.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.ai.entity.dto.AiRequestBodyDTO;
import com.tangyuan.ai.entity.dto.AiRequestImageBodyDTO;
import com.tangyuan.ai.entity.dto.DialogueDTO;
import com.tangyuan.ai.entity.dto.DialogueQueryDTO;
import com.tangyuan.ai.entity.enums.AiRoleEnum;
import com.tangyuan.ai.entity.enums.ModelTypeEnum;
import com.tangyuan.ai.entity.enums.TextTypeEnum;
import com.tangyuan.ai.entity.vo.*;
import com.tangyuan.ai.mapper.AiDialogueMapper;
import com.tangyuan.ai.service.AiDialogueService;
import com.tangyuan.ai.service.AiModelService;
import com.tangyuan.ai.service.AiRoleMaskService;
import com.tangyuan.ai.util.AiUtil;
import com.tangyuan.ai.entity.model.AiDialogue;
import com.tangyuan.common.constant.RedisConstant;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.common.util.BeanUtils;
import com.tangyuan.common.util.CommStatus;
import com.tangyuan.common.util.PictureOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
@Slf4j
public class AiDialogueServiceImpl extends ServiceImpl<AiDialogueMapper, AiDialogue> implements AiDialogueService {

    @Autowired
    AiModelService aiModelService;
    @Autowired
    AiRoleMaskService aiRoleMaskService;
    @Autowired
    AiUtil aiUtil;

    @Override
    public Result<AiDialogueVo> sendChat(Long userId, DialogueDTO dto) {
        AiDialogueVo dialogueVo = new AiDialogueVo();
        String key = RedisConstant.AI_REQUEST_CHAT + userId;
        //验证用户是否有结果在生成
        Object exists = CommStatus.viewCacheExists(key, dto.getContent(), 60, TimeUnit.SECONDS);
        if(exists != null){
            dialogueVo.setContent(ResultCodeEnum.AWAIT_THE_RESULT.getMessage());
            return Result.ok(dialogueVo);
        }
        //用户请求对象
        AiDialogue userDia = AiDialogue.builder()
                .role(AiRoleEnum.USER.role)
                .content(dto.getContent())
                .userId(userId)
                .modelId(dto.getModelId())
                .aiRoleMaskId(dto.getAiRoleMaskId())
                .createTime(new Date()).build();
        //Ai响应对象
        AiDialogue assistant = AiDialogue.builder()
                .role(AiRoleEnum.ASSISTANT.role)
                .userId(userId)
                .requestContent(dto.getContent())
                .modelId(dto.getModelId())
                .aiRoleMaskId(dto.getAiRoleMaskId())
                .build();
        switch (ModelTypeEnum.getModelTypeEnum(dto.getModelId())){
            case AI_DRAWING:
                if(dto.getContent().length() >= 190){
                    assistant.setContent("您的描述过长,请删减后重试.");
                    break;
                }
                AiTaskVo data = this.sendChatImage(dto).getData();
                if(data == null){
                    data = new AiTaskVo();
                }
                assistant.setImage(PictureOSSUtils.upload(data.getImg()));
                assistant.setTextType(TextTypeEnum.IMAGE.type);
                break;
            default:
                MessageVo messageVo = this.sendChatMessage(userId,dto);
                assistant.setContent(messageVo.getResult());
                assistant.setTokens(messageVo.getUsage().getCompletionTokens());
                assistant.setTextType(TextTypeEnum.TEXT.type);
                userDia.setTokens(messageVo.getUsage().getPromptTokens());
                break;
        }
        assistant.setCreateTime(new Date());
        //保存对话记录
        this.saveBatch(Arrays.asList(userDia,assistant));
        BeanUtils.copyProperties(assistant,dialogueVo);
        CommStatus.delete(key);
        return Result.ok(dialogueVo);
    }

    private AiImageTaskVo sendChatImage(DialogueDTO dto) {
        AiRequestImageBodyDTO bodyDTO = new AiRequestImageBodyDTO();
        bodyDTO.setText(dto.getContent());
        return aiUtil.dialogueImages(bodyDTO);
    }

    private MessageVo sendChatMessage(Long userId, DialogueDTO dto) {
        AiRequestBodyDTO bodyDTO = new AiRequestBodyDTO();
        bodyDTO.setMessages(Collections.singletonList(new RequestMessageVo(AiRoleEnum.USER.role, dto.getContent())));
        bodyDTO.setUserId(userId);
        bodyDTO.setEnableSystemMemory(true);
        bodyDTO.setSystemMemoryId(userId.toString());
        bodyDTO.setSystem(aiRoleMaskService.getMaskContent(dto.getAiRoleMaskId()));
        return aiUtil.dialogueMessage(bodyDTO);
    }

    /**
     * 根据用户和模型ID查询 对话内容
     * @param userId 用户ID
     * @param dto 模型Id 和 分页数据
     * @return 对话内容
     */
    @Override
    public Page<AiDialogueVo> getAiDialogueVoByUserId(Long userId, DialogueQueryDTO dto) {
        QueryWrapper<AiDialogue> wrapper = this.queryCondition(userId,dto);
        return baseMapper.getAiDialogueVoByUserId(new Page<>(dto.getPageNum(),dto.getPageSize()),wrapper);
    }

    @Override
    public Result deleteDialogue(Long userId, List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return Result.fail(ResultCodeEnum.NO_SEARCH_DATA.getMessage());
        }
        boolean remove = this.remove(new LambdaQueryWrapper<AiDialogue>()
                .eq(AiDialogue::getUserId, userId)
                .in(AiDialogue::getId, ids));
        if(remove){
            return Result.ok();
        }
        return Result.fail(ResultCodeEnum.NO_SEARCH_DATA.getMessage());
    }

    private QueryWrapper<AiDialogue> queryCondition(Long userId,DialogueQueryDTO dto) {
        QueryWrapper<AiDialogue> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AiDialogue::getUserId, userId);
        wrapper.lambda().eq(dto.getMaskId() != null && dto.getMaskId() > 0,AiDialogue::getAiRoleMaskId, dto.getMaskId());
        wrapper.lambda().eq(dto.getModelId() != null && dto.getModelId() > 0,AiDialogue::getModelId, dto.getModelId());
        wrapper.lambda().eq(AiDialogue::getIsDelete, 0);
        wrapper.lambda().orderByDesc(AiDialogue::getCreateTime).orderByDesc(AiDialogue::getId);
        return wrapper;
    }
}